<template>
	<view class="container">
		<canvas canvas-id="levelCanvas" id="levelCanvas" class="canvas" @touchend="handleClick" />
		<button @click="scrollToIndex(3)">scrollToIndex</button>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				levels: ['普通店铺', '黄金店铺', '钻石店铺', '星耀店铺', '荣耀店铺'],
				currentIndex: 2,
				animatingIndex: 2,
				animationFrame: null
			};
		},
		mounted() {
			this.drawCanvas();
		},
		methods: {
			drawCanvas() {
				const ctx = uni.createCanvasContext('levelCanvas', this);
				const canvasWidth = 375;
				const canvasHeight = 100;

				const centerX = canvasWidth / 2;
				const baseY = 20;
				const controlY = baseY + 60;

				const margin = 20;
				const leftX = margin;
				const rightX = canvasWidth - margin;

				// 灰色底线
				ctx.beginPath();
				ctx.setStrokeStyle('#444');
				ctx.setLineWidth(3);
				ctx.moveTo(leftX, baseY);
				ctx.quadraticCurveTo(centerX, controlY, rightX, baseY);
				ctx.stroke();

				// 高光渐变线
				const t = this.animatingIndex / (this.levels.length - 1);
				const glowWidth = 0.06;
				const highlightStartT = Math.max(0, t - glowWidth * 4);
				const highlightEndT = Math.min(1, t + glowWidth * 4);
				const xStart = leftX + highlightStartT * (rightX - leftX);
				const yStart = this.getQuadraticY(highlightStartT, baseY, controlY);
				const xEnd = leftX + highlightEndT * (rightX - leftX);
				const yEnd = this.getQuadraticY(highlightEndT, baseY, controlY);

				const gradient = ctx.createLinearGradient(xStart, yStart, xEnd, yEnd);
				gradient.addColorStop(0, 'rgba(255,255,255,0)');
				gradient.addColorStop(0.5, '#fff');
				gradient.addColorStop(1, 'rgba(255,255,255,0)');

				ctx.beginPath();
				ctx.setStrokeStyle(gradient);
				ctx.setLineWidth(4);
				ctx.moveTo(leftX, baseY);
				ctx.quadraticCurveTo(centerX, controlY, rightX, baseY);
				ctx.stroke();

				// 节点和文字
				const len = this.levels.length;
				const offsetT = 0.1;

				for (let i = 0; i < len; i++) {
					const rawT = i / (len - 1);
					const tPoint = offsetT + (1 - 2 * offsetT) * rawT;

					const x = leftX + tPoint * (rightX - leftX);
					const y = this.getQuadraticY(tPoint, baseY, controlY);

					const distance = Math.abs(this.animatingIndex - i);
					const isActive = distance < 0.01;
					const fontSize = 12 + (1 - Math.min(distance, 1)) * 2;

					if (isActive) {
						ctx.beginPath();
						ctx.setFillStyle('#fff');
						ctx.arc(x, y, 6, 0, 2 * Math.PI);
						ctx.fill();
						ctx.setFillStyle('#fff');
					} else {
						ctx.setFillStyle('#888');
					}

					ctx.setFontSize(fontSize);
					ctx.setTextAlign('center');
					ctx.fillText(this.levels[i], x, y + 30);
				}

				// 绘制滚动的高光点
				const tPoint = offsetT + (1 - 2 * offsetT) * t;
				const glowX = leftX + tPoint * (rightX - leftX);
				const glowY = this.getQuadraticY(tPoint, baseY, controlY);

				ctx.setFillStyle('#fff');
				ctx.beginPath();
				ctx.arc(glowX, glowY, 5, 0, 2 * Math.PI);
				ctx.fill();

				ctx.draw();
			},


			getQuadraticY(t, startY, controlY) {
				return (
					(1 - t) * (1 - t) * startY +
					2 * (1 - t) * t * controlY +
					t * t * startY
				);
			},

			handleClick(e) {
				const touch = e.changedTouches[0];
				const clickX = touch.x;
				const clickY = touch.y;

				const canvasWidth = 375;
				const baseY = 20;
				const controlY = baseY + 60;
				const margin = 20;
				const leftX = margin;
				const rightX = canvasWidth - margin;

				const len = this.levels.length;

				const offsetT = 0.1;

				for (let i = 0; i < len; i++) {
					const rawT = i / (len - 1);
					const t = offsetT + (1 - 2 * offsetT) * rawT;

					const x = leftX + t * (rightX - leftX);
					const y = this.getQuadraticY(t, baseY, controlY);

					if (
						Math.abs(clickX - x) < 30 &&
						Math.abs(clickY - (y + 30)) < 20
					) {
						this.animateToIndex(i);
						break;
					}
				}

			},
			scrollToIndex(targetIndex) {
				if (this.animationFrame) {
					this.cancelAnimationFrame(this.animationFrame); // 取消之前的动画帧
					this.animationFrame = null;
				}

				const duration = 300;
				const start = Date.now();
				const startIndex = this.animatingIndex;

				const animate = () => {
					const now = Date.now();
					const elapsed = now - start;
					const t = Math.min(elapsed / duration, 1);
					const easeT = 0.5 - 0.5 * Math.cos(Math.PI * t); // 缓动函数

					this.animatingIndex = startIndex + (targetIndex - startIndex) * easeT;
					this.drawCanvas();

					if (t < 1) {
						this.animationFrame = this.requestAnimationFrame(animate);
					} else {
						this.currentIndex = targetIndex;
						this.animatingIndex = targetIndex;
						this.animationFrame = null;
					}
				};

				animate();
			},

			animateToIndex(targetIndex) {

				if (this.animationFrame) this.cancelAnimationFrame(this.animationFrame);

				const duration = 300;
				const start = Date.now();
				const startIndex = this.animatingIndex;

				const animate = () => {
					const now = Date.now();
					const elapsed = now - start;
					const t = Math.min(elapsed / duration, 1);
					const easeT = 0.5 - 0.5 * Math.cos(Math.PI * t);

					this.animatingIndex =
						startIndex + (targetIndex - startIndex) * easeT;
					this.drawCanvas();

					if (t < 1) {
						this.animationFrame = this.requestAnimationFrame(animate);
					} else {
						this.currentIndex = targetIndex;
						this.animatingIndex = targetIndex;
					}
				};

				animate();
			},
			requestAnimationFrame(callback) {
				return setTimeout(() => {
					callback();
				}, 1000 / 60);
			},

			cancelAnimationFrame(id) {
				clearTimeout(id);
			},
		}
	};
</script>

<style>
	.container {
		background: #111;
	}

	.canvas {
		width: 100%;
		height: 100px;
	}
</style>